package us.gaaoc.framework.webapp.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import org.apache.myfaces.custom.fileupload.UploadedFileDefaultFileImpl;

import us.gaaoc.framework.dao.ModelFacadeHibernate;
import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.Court;
import us.gaaoc.framework.model.DocumentInstance;
import us.gaaoc.framework.model.DocumentStatus;
import us.gaaoc.framework.model.Documents;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.model.constants.Constants;
import us.gaaoc.framework.util.DateUtil;
import us.gaaoc.framework.util.pdf.Concatenate;

/**
 * Servlet implementation class FileUploader
 */
public class FileUploader extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final Logger LOG = Logger
			.getLogger(FileUploader.class);
	protected void doPost(HttpServletRequest request,
						  HttpServletResponse response) 
						  throws ServletException, IOException {
		UploadedFile myFile = null;
		String docType = null;
		String ajaxUpdateResult = "";
		boolean asExhibit = false;
		
		try {
			List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
			
			for (FileItem item : items) {
				
				if (item.isFormField()) {
					if(item.getFieldName().equalsIgnoreCase("asExhibitCheckbox"))
						asExhibit=Boolean.parseBoolean(item.getString() );
					else 
						docType= item.getString();
				} else {
					myFile=new UploadedFileDefaultFileImpl(item);
				}
			}
		
			ajaxUpdateResult = uploadFile(request,docType,myFile,asExhibit);
			
		} catch (FileUploadException e) {
			throw new ServletException("Parsing file upload failed.", e);
		} catch (Exception e) {
			throw new ServletException("Parsing file upload failed.", e);
		}

		response.getWriter().print(ajaxUpdateResult);
	}
	private String uploadFile(HttpServletRequest request,String docType, UploadedFile myFile, boolean asExhibit) throws IOException {
		CaseRecord cr = null;
		StringBuilder str=new StringBuilder();
		String caseRecordUuid = (String)  request.getSession().getAttribute("caseUuid");
		String courtUuid = (String)  request.getSession().getAttribute("courtUuid");
		Court court = null;
		String cvNumber = "";
		int externalCaseCategoryCode = 2;
		boolean contempt;
		if(externalCaseCategoryCode == 2 && courtUuid.equalsIgnoreCase("courtUuid4")) {
			contempt = true;
		}
		else
			contempt = false;
		Person filer = (Person) request.getSession().getAttribute("person");
		
		// TODO: confirm assumption that we only need the filer here if we are creating a new case. 
		if(filer == null && caseRecordUuid == null)
		{
			str.append(" There is no user!");
			return str.toString();
			
		}
		
		
		if (caseRecordUuid != null)
		{
			cr=ModelFacadeHibernate.getInstance().findCaseRecordById(caseRecordUuid, courtUuid);
			//court = ModelFacadeHibernate.getInstance().findCourtByUuid(this.getCr().getCourtUuid());
			court = (Court) request.getSession().getAttribute("court");
		}else{
			if(courtUuid != null && court == null)
			{
				court = ModelFacadeHibernate.getInstance().findCourtByUuid(courtUuid);
			}else{
				str.append(" There is no Case Filing and No Court!");																		
				return str.toString();
			}
		}
		
		
		
		
		if(contempt == true && courtUuid.equalsIgnoreCase("courtUuid4") && !cvNumber.equals("") && !asExhibit){
			
			boolean exists = ModelFacadeHibernate.getInstance().findCivilActionNumber(cvNumber, courtUuid);
			
			if (exists) {
				LOG.info("Case already exists for the civil action number " + cvNumber);
				str.append("Case already exists for the civil action number " + cvNumber);
				return str.toString();
			}
		}

		byte[] fileBytes = myFile.getBytes();
		InputStream inStream = myFile.getInputStream();
		
		// case record already created
		if (caseRecordUuid != null) {			
						
			
			//this.setCr(ModelFacadeHibernate.getInstance().findCaseRecordById(caseRecordUuid, courtUuid));
			if (myFile.getContentType().equalsIgnoreCase("application/pdf")) {
				if (docType.equalsIgnoreCase("DATA FILE")) {
					LOG.info("Inside the checking of the title of the pdf..");
					str.append("DATA FILE is not a title of a pdf's allowed for upload ");
					return str.toString();
					
				}				
				//SUCCESS
				cr.setCaseRecordAction(ModelFacadeHibernate.getInstance().getCaseRecordActionsById(externalCaseCategoryCode));
				if(asExhibit)
				{
					Documents toAppend = null;
					boolean docExists = false;
					for(Documents d : cr.getDocuments())
					{
						int docCode = d.getDocumentInstance().getCode();
						int docStatus = d.getStatus().getCode();
						if(docCode == Integer.parseInt(docType) 
								&& (d.getStatus().getCode() == 1 || d.getStatus().getCode() == 4 || d.getStatus().getCode() == 6))
						{
							toAppend = d;
							docExists = true;
							break;
						}
					}
					if(docExists)
					{
						File newFile = File.createTempFile(UUID.randomUUID().toString(),".pdf",
								new File("C:" + File.separator + "temp" + File.separator));
						FileOutputStream fw = new FileOutputStream(newFile);
						fw.write(fileBytes);
						fw.flush();
						fw.close();
						
						ModelFacadeHibernate.getInstance().addCaseRecordHistory(caseRecordUuid, Constants.CaseRecordEventType.FILING_CREATED_BY_LEGAL_PREPARER, filer,court.getUuid(), "Added Exhibit");
						cr.getFiler().add(filer);
						
						Concatenate concatenate = new Concatenate();
						concatenate.concatenateHelper(toAppend, newFile.getAbsolutePath());
						
						ModelFacadeHibernate.getInstance().getSession().saveOrUpdate(cr);	
						
						str.append(" Appended exhibit to end of the document " + toAppend.getDocumentInstance().getDescription());
						return "upload";
					}else{
						str.append(" There is no document named $TITLE to add exhibit to.".replace("$TITLE",
										ModelFacadeHibernate.getInstance().findDocumentInstanceByCode(Integer.parseInt(docType)).getDescription()));																		
						return str.append("failure").toString();
					}
				}
				

				
				if(docType.equals("")) return "failure";
	
				Documents doc = new Documents();
				
				DocumentInstance documentInstance = ModelFacadeHibernate.getInstance()
						.findDocumentInstanceByCode(Integer
								.parseInt(docType));
				
				DocumentStatus ds = new DocumentStatus();
				ds = ModelFacadeHibernate.getInstance().findDocumentStatus(6);
				
				Person personSigned = (Person) request.getSession().getAttribute("person");
				String tempTitle = documentInstance.getDescription();
				doc.setTitle(tempTitle.replace(' ', '_')
					.replace(",_", "_").replace('-', '_')
					.replace(':', '_').replace('\'', '_'));
				
				doc.setPhysicalType("pdf");
				doc.setDocumentInstance(documentInstance);
				doc.setReceivedDateTime(DateUtil.getCurrentDate());
				doc.setStatus(ds);
				doc.setPerson(personSigned);
				cr = ModelFacadeHibernate.getInstance().findCaseRecordById(
						caseRecordUuid, courtUuid);
				doc.setCaseRecord(cr);
				
				ModelFacadeHibernate.getInstance().makePersistent(doc);
				doc.setContent(null,fileBytes);
			
				List<Documents> listOfDoc = new ArrayList<Documents>();
				listOfDoc = ModelFacadeHibernate.getInstance().findDocumentsByCaseUuid(
						caseRecordUuid);
			
				ModelFacadeHibernate.getInstance().addCaseRecordHistory(caseRecordUuid, Constants.CaseRecordEventType.FILING_CREATED_BY_LEGAL_PREPARER, personSigned,court.getUuid(), "");
				cr.getFiler().add(personSigned);
				
				
				// This is for revmods
				if(documentInstance.getDocumentType().getCode() == Constants.DocumentType.REVIEW_MODIFICATION
					&& cr.getCourt().getUuid().equals("courtUuidClarke"))						
				{
					// move witness to defendent			
					for(PersonParticipants pp : cr.getPersonParticipants())
					{
						if(pp.getRelationship().getCode() == Constants.ParticipantRelationship.Witness)
						{
							pp.setRelationship(
									ModelFacadeHibernate.getInstance().findParticipantRelationship(Constants.ParticipantRelationship.DefendantParty));
							ModelFacadeHibernate.getInstance().addCaseRecordHistory(
									caseRecordUuid, 
									Constants.CaseRecordEventType.COOPERATING_PARTY_MOVED_AS_DEFENDANT, 
									personSigned,
									court.getUuid(), "");
							ModelFacadeHibernate.getInstance().getSession().saveOrUpdate(pp);				
						}
					}
				}
								
				str.append("upload");
			}
			// not a pdf file
			else {
				str.append("A text file has been already uploaded. Please upload a pdf file if there's any. ");
				
				//setLockUploadProcess(false);
				LOG.error("Text file already uploaded");
				str.append("failure");
			}
		}
		return str.toString();
		
	}

}
